package cn.ddiancan.gateway.config;

import cn.ddiancan.gateway.filter.AccessFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.server.WebFilter;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Configuration
public class FilterConfig {

    private static final String CONTEXT_PATH = "/xddcloud/";

    @Value("${cloud.gateway.access.white-list:}")
    private String whiteListStr;

    @Bean
    public AccessFilter webFilter() {
        List<String> whiteList = StringUtils.hasText(whiteListStr) ? new ArrayList<>(
            StringUtils.commaDelimitedListToSet(whiteListStr)) : Collections.emptyList();
        return new AccessFilter(whiteList);
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public WebFilter customWebFilter() {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String rawPath = request.getURI().getRawPath();
            if (!rawPath.startsWith(CONTEXT_PATH)) {
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.BAD_GATEWAY);
                DataBuffer buffer = response.bufferFactory().wrap(HttpStatus.BAD_GATEWAY.getReasonPhrase().getBytes());
                return response.writeWith(Mono.just(buffer));
            }
            String newPath = rawPath.replaceFirst(CONTEXT_PATH, "/");
            ServerHttpRequest newRequest = request.mutate().path(newPath).build();
            return chain.filter(exchange.mutate().request(newRequest).build());
        };
    }
}
